home *** CD-ROM | disk | FTP | other *** search
- From: decvax!vax135!hou3c!ka
- Date: Mon, 21 Jan 85 21:54:50 est
- Newsgroups: mod.sources
- Subject: Vnews part 2
-
- # Welcome to vnews release 2.11-B 1/17/85.
- # This is part 2 out of 7.
- # Feed me into sh (NOT csh).
-
- if test ! -d artfile
- then mkdir artfile
- fi
-
- if test ! -d lib
- then mkdir lib
- fi
-
- cat > artfile/ifuncs.c.10.2 <<\!E!O!F!
- /*
- * ifuncs - functions used by inews.
- */
-
- #ifndef lint
- static char *SccsId = "@(#)ifuncs.c 2.35 9/12/84";
- #endif !lint
-
- #include "iparams.h"
- #include <errno.h>
-
- /*
- * Transmit this article to all interested systems.
- */
-
- #ifdef u370
- static struct srec srec;
- #endif
-
- static struct hbuf h, hh;
-
- broadcast()
- {
- register char *nptr, *hptr;
- register FILE *fp;
- #ifndef u370
- struct srec srec;
- #endif
- char sentbuf[BUFLEN];
- int nsent = 0;
-
- /* h is a local copy of the header we can scribble on */
- fp = xfopen(ARTICLE, "r");
- if (hread(&h, fp, TRUE) == NULL)
- xerror("Cannot reread article");
- fclose(fp);
-
- strcpy(sentbuf, h.ident);
- strcat(sentbuf, " sent to ");
- nsent = 0;
- /* break path into list of systems. */
- hptr = nptr = h.path;
- while (*hptr != '\0') {
- if (index(NETCHRS, *hptr)) {
- *hptr++ = '\0';
- nptr = hptr;
- } else
- hptr++;
- }
- *nptr = '\0';
-
- /* loop once per system. */
- lock();
- s_openr();
- while (s_read(&srec)) {
- if (strncmp(srec.s_name, FULLSYSNAME, SNLN) == 0)
- continue;
- hptr = h.path;
- while (*hptr != '\0') {
- if (strncmp(srec.s_name, hptr, SNLN) == 0)
- goto contin;
- while (*hptr++ != '\0')
- ;
- }
- if (ngmatch(h.nbuf, srec.s_nbuf)) {
- if (h.distribution[0] == '\0' ||
- ngmatch(h.distribution, srec.s_nbuf) ||
- ngmatch(h.nbuf, h.distribution)) {
- if (transmit(&srec, xfopen(ARTICLE, "r"), 1)) {
- if (nsent)
- strcat(sentbuf, ", ");
- strcat(sentbuf, srec.s_name);
- nsent++;
- }
- }
- }
- contin:;
- }
- if (nsent)
- log(sentbuf);
- s_close();
- unlock();
- }
-
- /*
- * Transmit file to system.
- */
- #define PROC 0004
- transmit(sp, ifp, maynotify)
- register struct srec *sp;
- register FILE *ifp;
- int maynotify;
- {
- register FILE *ofp;
- register int c;
- register char *ptr;
- char TRANS[BUFLEN];
- char *argv[20];
- register int pid;
- extern char firstbufname[];
-
- /* A: afmt: the other machine runs an A news, so we xmit in A format */
- int afmt = (index(sp->s_flags, 'A') != NULL);
- /* B: use B format (this is the default - don't use this letter elsewise). */
- /* F: append name to file */
- int appfile = (index(sp->s_flags, 'F') != NULL);
- /* H: history: expand %s into the history line (KSA) */
- int history = (index(sp->s_flags, 'H') != NULL); /* (6/18/84 KSA) */
- /* L: local: don't send the article unless it was generated locally */
- int local = (index(sp->s_flags, 'L') != NULL);
- /* N: notify: don't send the article, just tell him we have it */
- int notify = maynotify && (index(sp->s_flags, 'N') != NULL);
- /* S: noshell: don't fork a shell to execute the xmit command */
- int noshell = (index(sp->s_flags, 'S') != NULL);
- /* U: useexist: use the -c option to uux to use the existing copy */
- int useexist = (index(sp->s_flags, 'U') != NULL);
-
- if (local && mode == PROC) {
- fclose(ifp);
- return FALSE;
- }
- #ifdef DEBUG
- printf("Transmitting to '%s'\n", sp->s_name);
- #endif
- if (!appfile && !useexist && !history) { /* (6/18/84 KSA) */
- if (hread(&hh, ifp, TRUE) == NULL) {
- logerr("Bad header, not transmitting %s re %s to %s",
- hh.ident, hh.title, sp->s_name);
- fclose(ifp);
- return FALSE;
- }
- if (hh.nbuf[0] == '\0') {
- fprintf(stderr, "Article not subscribed to by %s\n", sp->s_name);
- fclose(ifp);
- return FALSE;
- }
- sprintf(TRANS, "%s/trXXXXXX", SPOOL);
- }
-
- if (notify) {
- char oldid[50];
- sprintf(hh.title, "ihave %s %s", hh.ident, FULLSYSNAME);
- sprintf(hh.nbuf, "to.%s.ctl", sp->s_name);
- strcpy(oldid, hh.ident);
- getident(&hh);
- log("tell %s about %s, notif. id %s",
- sp->s_name, oldid, hh.ident);
- }
-
- if (appfile) {
- if (firstbufname[0] == '\0') {
- extern char histline[];
- localize("junk");
- savehist(histline);
- xerror("No file name to xmit from");
- }
- #ifdef IHCC
- sprintf(TRANS, "%s/%s/%s", logdir(HOME), BATCHDIR, sp->s_xmit);
- ofp = fopen(TRANS, "a");
- #else
- ofp = fopen(sp->s_xmit, "a");
- #endif
- if (ofp == NULL)
- xerror("Cannot append to %s", sp->s_xmit);
- fprintf(ofp, "%s\n", firstbufname);
- fclose(ofp);
- fclose(ifp);
- return TRUE;
- }
- else
- #ifdef UXMIT
- if (useexist) {
- if (firstbufname[0] == '\0')
- xerror("No file name to xmit from");
- if (*sp->s_xmit == '\0')
- sprintf(bfr, UXMIT, sp->s_name, firstbufname);
- else
- sprintf(bfr, sp->s_xmit, firstbufname);
- fclose(ifp);
- } else
- #endif
- if (history) { /* (6/18/84 KSA) */
- extern char histline[];
- if (*sp->s_xmit == '\0')
- xerror("no xmit command with H flag");
- sprintf(bfr, sp->s_xmit, histline);
- } else
- {
- ofp = xfopen(mktemp(TRANS), "w");
- if (afmt)
- ohwrite(&hh, ofp);
- else
- hwrite(&hh, ofp);
- if (!notify)
- while ((c = getc(ifp)) != EOF)
- putc(c, ofp);
- fclose(ifp);
- fclose(ofp);
- if (*sp->s_xmit == '\0')
- sprintf(bfr, DFTXMIT, sp->s_name, TRANS);
- else
- sprintf(bfr, "(%s) < %s", sp->s_xmit, TRANS);
- }
-
- /* At this point, the command to be executed is in bfr. */
- if (noshell) {
- if (pid = fork())
- fwait(pid);
- else {
- close(0);
- open(TRANS, 0);
- if (*sp->s_xmit == '\0')
- ptr = bfr;
- else
- ptr = sp->s_xmit;
- for (pid = 0; pid < 19; pid++) {
- while (isspace(*ptr))
- *ptr++ = 0;
- argv[pid] = ptr;
- while (!isspace(*++ptr) && *ptr)
- ;
- if (!*ptr)
- break;
- }
- argv[++pid] = 0;
- execv(argv[0], argv);
- xerror("Can't execv %s", argv[0]);
- }
- } else
- system(bfr);
- if (!appfile && !useexist && !history) /* 6/18/84 KSA) */
- unlink(TRANS);
- fclose(ifp);
- return TRUE;
- }
-
- typedef struct {
- char *dptr;
- int dsize;
- } datum;
-
- /*
- * Return TRUE if we have seen this file before, else FALSE.
- */
- history(hp)
- struct hbuf *hp;
- {
- #ifdef DBM
- datum lhs, rhs;
- datum fetch();
- #else !DBM
- register FILE *hfp;
- #endif !DBM
- register char *p;
- char lcident[BUFLEN];
-
- #ifdef DEBUG
- fprintf(stderr,"history(%s)\n", hp->ident);
- #endif
- /*
- * Make the article ID case insensitive.
- */
- strcpy(lcident, hp->ident);
- p = lcident;
- while (*++p)
- if (isupper(*p))
- *p = tolower(*p);
-
- idlock(lcident);
- #ifdef DBM
- dbminit(ARTFILE);
- lhs.dptr = lcident;
- lhs.dsize = strlen(lhs.dptr) + 1;
- rhs = fetch(lhs);
- if (rhs.dptr)
- return(TRUE);
- #else
- hfp = xfopen(ARTFILE, "r");
- while (fgets(bfr, BUFLEN, hfp) != NULL) {
- p = index(bfr, '\t');
- if (p == NULL)
- p = index(bfr, '\n');
- if (p != NULL) /* can happen if nulls in file */
- *p = 0;
- p = bfr;
- while (*++p)
- if (isupper(*p))
- *p = tolower(*p);
-
- if (strcmp(bfr, lcident)==0 ||
- hp->oident[0] && strcmp(bfr, hp->oident)==0) {
- fclose(hfp);
- idunlock();
- #ifdef DEBUG
- fprintf(stderr,"history returns true\n");
- #endif
- return(TRUE);
- }
- }
- fclose(hfp);
- #endif
- addhist(hp->ident);
- addhist("\t");
- #ifdef DEBUG
- fprintf(stderr,"history returns false\n");
- #endif
- return(FALSE);
- }
-
- char histline[256]; /* Assumed initially zero */
-
- addhist(msg)
- char *msg;
- {
- strcat(histline, msg);
- }
-
- savehist(hline)
- char *hline;
- {
- register FILE *hfp;
- datum lhs, rhs;
- long fpos;
- register char *p;
-
- hfp = xfopen(ARTFILE, "a");
- fpos = ftell(hfp);
- fprintf(hfp, "%s\n", hline);
- fclose(hfp);
- #ifdef DBM
- /* We assume that history has already been called, calling dbminit. */
- p = index(hline, '\t');
- if (p)
- *p = 0;
- p = hline;
- while(*++p)
- if(isupper(*p))
- *p = tolower(*p);
- lhs.dptr = hline;
- lhs.dsize = strlen(lhs.dptr) + 1;
- rhs.dptr = (char *) &fpos;
- rhs.dsize = sizeof fpos;
- store(lhs, rhs);
- #endif
- hline[0] = 0;
- idunlock();
- }
-
- /*
- * Save partial news.
- */
- newssave(fd, dummy)
- FILE *fd;
- char *dummy;
- {
- register FILE *tofd, *fromfd;
- char sfname[BUFLEN];
- register int c;
- time_t tim;
-
- #ifdef lint
- c = *dummy;
- #endif lint
-
- if (fd == NULL)
- fromfd = xfopen(INFILE, "r");
- else
- fromfd = fd;
- umask(savmask);
- setgid(gid);
- setuid(uid);
-
- sprintf(sfname, "%s/%s", userhome, PARTIAL);
- if ((tofd = fopen(sfname, "a")) == NULL)
- xerror("Cannot save partial news in %s", sfname);
- time(&tim);
- fprintf(tofd, "----- News saved at %s\n", arpadate(&tim));
- while ((c = getc(fromfd)) != EOF)
- putc(c, tofd);
- fclose(fromfd);
- fclose(tofd);
- printf("News saved in %s\n", sfname);
- xxit(0);
- }
-
- /*
- * Handle dates in header.
- */
-
- dates(hp)
- struct hbuf *hp;
- {
- time_t edt;
-
- time(&hp->rectime);
- strcpy(hp->recdate, arpadate(&hp->rectime));
- nstrip(hp->recdate);
- if (*hp->subdate) {
- if (cgtdate(hp->subdate) < 0) {
- xerror("Cannot parse submittal date '%s'", hp->subdate);
- }
- } else
- strcpy(hp->subdate, hp->recdate);
- if (*hp->expdate) {
- if ((edt = cgtdate(hp->expdate)) < 0)
- xerror("Cannot parse expiration date '%s'",hp->expdate);
- nstrip(strcpy(hp->expdate, arpadate(&edt)));
- } else {
- defexp = TRUE;
- /*
- * Default is now applied in expire.c
- hp->exptime = hp->rectime + DFLTEXP;
- nstrip(strcpy(hp->expdate, arpadate(&hp->exptime)));
- */
- }
- }
-
- char lockname[80];
- idlock(str)
- char *str;
- {
- register int i;
- char tempname[80];
- time_t now;
- struct stat sbuf;
- #ifdef VMS
- int fd;
-
- sprintf(lockname, "/tmp/%s.l.1", str);
- if ((fd = creat(lockname, 0444)) < 0) {
- #else !VMS
- sprintf(tempname, "/tmp/LTMP.%d", getpid());
- sprintf(lockname, "/tmp/L%s", str);
- #ifdef FOURTEENMAX
- lockname[5 /* /tmp/ */ + 14] = '\0';
- #endif
- close(creat(tempname, 0666));
- while (link(tempname, lockname)) {
- #endif !VMS
- (void) time(&now);
- i = stat(lockname, &sbuf);
- if (i < 0) {
- xerror("Directory permission problem in /tmp");
- }
- if (sbuf.st_mtime + 10*60 < now) {
- unlink(lockname);
- logerr("Article %s locked up", str);
- continue;
- }
- log("waiting on lock for %s", lockname);
- sleep((unsigned)60);
- }
- #ifdef VMS
- close(fd);
- #else
- unlink(tempname);
- #endif
- unlink(tempname);
- }
-
- idunlock()
- {
- unlink(lockname);
- }
-
- /*
- * Put a unique name into header.ident.
- */
- getident(hp)
- struct hbuf *hp;
- {
- long seqn;
- register FILE *fp;
-
- lock();
- fp = xfopen(SEQFILE, "r");
- fgets(bfr, BUFLEN, fp);
- fclose(fp);
- seqn = atol(bfr) + 1;
- #ifdef VMS
- unlink(SEQFILE);
- #endif VMS
- fp = xfopen(SEQFILE, "w");
- fprintf(fp, "%ld\n", seqn);
- fclose(fp);
- unlock();
- sprintf(hp->ident, "<%ld@%s%s>", seqn, FULLSYSNAME, MYDOMAIN);
- }
-
- /*
- * Check that header.nbuf contains only valid newsgroup names;
- * exit with error if not valid.
- *
- */
-
- ngfcheck(isproc)
- int isproc;
- {
- register char *s1, *s2;
- register FILE *f;
- register char *os1;
- int ngroups = 1;
- char tbuf[BUFLEN], ngcheck[AFSIZ];
-
- f = xfopen(ACTIVE, "r");
- s1 = ngcheck;
- while (fgets(bfr, BUFLEN, f) != NULL) {
- os1 = s1;
- for(s2 = bfr; *s2 != '\0' && *s2 != ' ';) {
- if (s1 >= &ngcheck[AFSIZ-2])
- xerror("ACTIVE file too long");
- *s1++ = *s2++;
- }
- *s1++ = '\0';
- if (isproc) /* don't check to see if can post to this group */
- continue;
- while (*s2++ != '\0' && *s2 != ' ')
- ; /* skip max article number */
- while (*s2++ != '\0' && *s2 != ' ')
- ; /* skip min article number */
- if (*s2++ != '\0' && *s2 == 'n')
- s1 = os1; /* can't post to this group */
- }
- *s1++ = '\0';
- *s1 = '\0';
- fclose(f);
-
- s1 = header.nbuf;
- s2 = nbuf;
- while (*s1 == NGDELIM || *s1 == ' ')
- s1++; /* skip leading junk */
- do {
- /* there shouldn't be blanks, but give the jerk a break */
- if (*s1 == NGDELIM || *s1 == ' ') {
- *s2++ = '\0';
- ngroups++;
- while (*++s1 == NGDELIM || *s1 == ' ')
- ; /* remove extra commas */
- } else
- *s2++ = *s1++;
- } while (*s1 != '\0');
- *s2 = '\0';
-
- s1 = nbuf;
- while (*s1 != '\0') { /* for each newsgroup in header */
- s2 = ngcheck;
- while (*s2 != '\0') { /* for each newsgroup in active file */
- if (strcmp(s1, s2) == 0)
- break;
- while (*s2++ != '\0')
- ;
- }
- if (*s2 == '\0') { /* not found. remove it */
- if (!isproc) {
- logerr("Invalid news group '%s'", s1);
- newssave(stdin, (char *)NULL);
- }
- /* See if it's in our alias list */
- f = xfopen(ALIASES,"r");
- while (fscanf(f,"%s %s", tbuf, bfr) == 2
- && strcmp(s1, tbuf))
- ;
- fclose(f);
- if (strcmp(s1, tbuf) == 0) {
- logerr("Aliased newsgroup '%s' to '%s'", s1, bfr);
- os1 = s1;
- s1 = nbuf;
- s2 = tbuf;
- while (s1 < os1) /* copy left part */
- *s2++ = *s1++;
- s1 = bfr;
- while (*s1 != '\0') /* copy alias */
- *s2++ = *s1++;
- *s2++ = '\0';
- s1 = os1;
- os1 = nbuf + (s2 - tbuf);
- while (*s1++ != '\0') /* skip old group */
- ;
- /* copy right part */
- tbufcpy(s2, s1);
- /* copy back to original buffer */
- tbufcpy(nbuf, tbuf);
- s1 = os1;
- } else {
- logerr("Unknown newsgroup '%s' removed", s1);
- s2 = s1;
- while (*s2++ != '\0') /* skip the bad one */
- ;
- tbufcpy(s1, s2);
- }
- } else { /* It's in our active file */
- os1 = s1;
- while (*s1++ != '\0')
- ;
- /* check for local only distribution on incoming
- newsgroups. This might occur if someone posted to
- general,net.unix */
- if(isproc && ngroups > 1 && index(os1, '.') == NULL) {
- logerr("Local group '%s' removed", os1);
- tbufcpy(os1, s1);
- s1 = os1;
- }
- }
- }
- /* remove any duplicates */
- os1 = s1 = nbuf;
- for(;;) {
- if (*s1++ == '\0') {
- if (*s1 == '\0')
- break;
- s2 = s1;
- while (*s2 != '\0') {
- if (strcmp(os1, s2) == 0) {
- logerr("Duplicate '%s' removed",os1);
- os1 = s2;
- while (*s2++ != '\0') /* skip it */
- ;
- tbufcpy(os1, s2);
- } else
- while (*s2++ != '\0')
- ;
- }
- os1 = s1;
- s1[-1] = '\0';
- }
- }
- if (nbuf[0] != '\0') {
- s1 = header.nbuf;
- s2 = nbuf;
- do {
- while (*s2 != '\0')
- *s1++ = *s2++;
- *s1++ = NGDELIM;
- } while (*++s2 != '\0');
- *s1 = '\0';
- return FALSE;
- }
- return TRUE;
- }
-
- tbufcpy(s1, s2)
- register char *s1, *s2;
- {
- do {
- while (*s2 != '\0')
- *s1++ = *s2++;
- *s1++ = '\0';
- } while (*++s2 != '\0');
- *s1 = '\0';
- }
-
-
- /*
- * Figure out who posted the article (which is locally entered).
- * The results are placed in the header structure hp.
- */
- gensender(hp, logname)
- struct hbuf *hp;
- char *logname;
- {
- register char *fn, *p;
- char buf[BUFLEN];
- char *fullname(), *getenv();
- int fd;
-
- fn = getenv("NAME");
-
- if (fn == NULL) {
- sprintf(buf, "%s/%s", userhome, ".name");
- fd = open(buf, 0);
- if (fd >= 0) {
- read(fd, buf, sizeof buf);
- close(fd);
- if (buf[0] >= 'A') {
- fn = buf;
- for (p=fn; *p; p++)
- if (*p < ' ')
- *p = '\0';
- }
- }
- }
-
- if (fn == NULL)
- fn = fullname(logname);
-
- sprintf(hp->path, "%s", logname);
- sprintf(hp->from, "%s@%s%s (%s)", logname, FULLSYSNAME, MYDOMAIN, fn);
- }
-
- /*
- * Trap interrupts.
- */
- onsig(n)
- int n;
- {
- static int numsigs = 0;
- /*
- * Most UNIX systems reset caught signals to SIG_DFL.
- * This bad design requires that the trap be set again here.
- * Unfortunately, if the signal recurs before the trap is set,
- * the program will die, possibly leaving the lock in place.
- */
- if (++numsigs > 100) {
- logerr("inews ran away looping on signal %d", n);
- xxit(1);
- }
- signal(n, onsig);
- sigtrap = n;
- }
-
- #ifdef BATCH
- /*
- * If the stdin begins with "#", we assume we have been fed a batched
- * shell script which looks like this:
- * #! rnews 1234
- * article with 1234 chars
- * #! rnews 4321
- * article with 4321 chars
- *
- * In this case we just exec the unbatcher and let it unpack and call us back.
- *
- * Note that there is a potential security hole here. If the batcher is
- * /bin/sh, someone could ship you arbitrary stuff to run as shell commands.
- * The main protection you have is that the effective uid will be news, not
- * uucp and not the super user. (That, plus the fact that BATCH is set to
- * "unbatch" as the system is distributed.) If you want to run a batched link
- * and you are security concious, do not use /bin/sh as the unbatcher.
- * the thing to do is to change BATCH in your localize.sh file from /bin/sh
- * to some restricted shell which can only run rnews.
- */
- checkbatch()
- {
- int c;
-
- c = getc(stdin);
- if (c != EOF)
- ungetc(c, stdin);
- clearerr(stdin);
- if (c == '#') {
- char unbatcher[BUFLEN];
-
- sprintf(unbatcher, "%s/%s", LIB, BATCH);
- reset_stdin();
- execl(unbatcher, "news-unpack", (char *)0);
- xerror("Unable to exec shell to unpack news.");
- }
- }
-
- /*
- * We've already done a read on stdin, and we want to seek back to the
- * beginning. We want the real file descriptor (beyond buffers) to
- * reflect the true beginning. Do whatever is necessary.
- */
- reset_stdin()
- {
- register FILE *ofd;
- register int c;
- char *ofdname;
- long lseek();
-
- /* First try to seek back - if so, it's a cheap way back. */
- if (lseek(0, 0L, 0) == 0L)
- return;
-
- /* Can't seek, so have to copy input to a file and use that. */
- ofdname = "/tmp/inewsXXXXX";
- mktemp(ofdname);
- ofd = fopen(ofdname, "w");
- while ((c=getc(stdin)) != EOF)
- putc(c, ofd);
- fclose(stdin);
- fclose(ofd);
-
- /* Now for a few lower level hacks to reopen stdin and make
- * absolutely sure that the right fd's are done for the exec.
- */
- (void) close(0); /* make sure stdin is really closed. */
- (void) open(ofdname, 0); /* should return zero */
- (void) unlink(ofdname); /* to avoid cleaning it up later. */
- }
- #endif BATCH
-
- /*
- * Exit and cleanup.
- */
- xxit(status)
- int status;
- {
- unlink(INFILE);
- unlink(ARTICLE);
- while (lockcount > 0)
- unlock();
- idunlock();
- exit(status);
- }
-
- rwaccess(fname)
- char *fname;
- {
- int fd;
-
- fd = open(fname, 2);
- if (fd < 0)
- return 0;
- close(fd);
- return 1;
- }
-
- exists(fname)
- char *fname;
- {
- int fd;
-
- fd = open(fname, 0);
- if (fd < 0)
- return 0;
- close(fd);
- return 1;
- }
-
- int lockcount = 0; /* no. of times we've called lock */
-
- #ifdef VMS
-
- #define SUBLOCK "/tmp/netnews.lck.1"
-
- /*
- * Newsystem locking.
- * These routines are different for VMS because we can not
- * effectively simulate links, and VMS supports multiple
- * version numbers of files
- */
- lock()
- {
- register int i;
- register int fd;
-
- if (lockcount++ == 0) {
- i = DEADTIME;
- while ((fd = creat(SUBLOCK, 0444)) < 0) {
- if (--i < 0) {
- unlink(SUBLOCK);
- fprintf(stderr,"%s: %s\n", Progname, msg);
- logerr("News system locked up");
- }
- if (i < -3)
- xerror("Unable to unlock news system");
- sleep((unsigned)1);
- }
- close(fd);
- }
- }
-
- unlock()
- {
- if (--lockcount == 0)
- unlink(SUBLOCK);
- }
-
- #else !VMS
-
- /*
- * Newsystem locking.
- */
-
- lock()
- {
- register int i;
- extern int errno;
-
- if (lockcount++ == 0) {
- i = DEADTIME;
- while (link(SUBFILE, LOCKFILE)) {
- if (errno != EEXIST)
- break;
- if (--i < 0)
- xerror("News system locked up");
- sleep((unsigned)1);
- }
- }
- }
-
- unlock()
- {
- if (--lockcount == 0)
- unlink(LOCKFILE);
- }
- #endif VMS
-
- /*
- * Generate the name of the person responsible for posting this article,
- * in order to check that two articles were posted by the same person.
- */
- char *
- senderof(hp)
- struct hbuf *hp;
- {
- char *q, *tp;
- char *tailpath();
-
- if (hp->sender[0])
- tp = hp->sender;
- else if (hp->from[0])
- tp = hp->from;
- else
- tp = tailpath(hp);
-
- /* Remove full name */
- q = index(tp, ' ');
- if (q)
- *q = '\0';
-
- q = malloc((unsigned)(strlen(tp) + 1));
- strcpy(q, tp);
- return q;
- }
- !E!O!F!
-
- cat > lib/addrc.c <<\!E!O!F!
- /*
- * Add a newsgroup onto the end of .newsrc.
- */
-
- #include <stdio.h>
- #include "defs.h"
- #include "newsrc.h"
-
-
- addrc(ngp)
- struct ngentry *ngp;
- {
- if (lastng != NULL) {
- lastng->ng_next = ngp;
- lastng = ngp;
- } else {
- lastng = firstng = ngp;
- }
- }
- !E!O!F!
-
- cat > lib/af.h <<\!E!O!F!
- #include "artfile.h"
- #include "stroff.h"
-
- /* length of section of artrec that can be written directly to artfile */
- #define A_WRTLEN (int)(stroff(a_nkwords, artrec) + 1)
-
- /* offsets */
- #define PARENTOFF (stroff(a_parent, artrec) + 1)
- #define CHILDRENOFF (stroff(a_children, artrec) + 1)
- #define CHILDCHOFF (stroff(a_childchain, artrec) + 1)
- #define GROUPOFF (stroff(a_group[0], artrec) + 1)
-
-
- #define A_PREFIX 0210 /* this byte precedes each article record */
- #define AF_MAGIC 0431 /* magic number to indicate artfile */
- #define AF_VERSION 1 /* version number */
-
-
- struct afheader {
- short af_magic; /* magic number (0431) */
- short af_version; /* version number */
- DPTR af_idtab; /* offset of message id hash table */
- DPTR af_nglist; /* pointer to newsgroup chain table */
- DPTR af_titletab; /* title hash table */
- DPTR af_records; /* start of article records */
- DPTR af_free; /* add next record here */
- short af_idtlen; /* # elements in message id hash table */
- short af_maxng; /* # elements in newsgroup chain table */
- short af_ttlen; /* # elements in title hash table */
- };
-
-
- extern struct afheader afhd ;
- extern int affd ;
-
- #if BUFSIZ == 1024
- #define BSIZE 1024
- #else
- #define BSIZE 512
- #endif
-
-
- DPTR readptr() ;
-
- #define ngchain(ngnum) (afhd.af_nglist + ngnum * (int)sizeof(DPTR))
- #define hashid(msgid) (afhd.af_idtab + hash(msgid, afhd.af_idtlen) * (int)sizeof(DPTR))
-
- #define equal(s1, s2) (strcmp(s1, s2) == 0)
- !E!O!F!
-
- cat > lib/aflock.c <<\!E!O!F!
- /*
- * Lock and unlock the article data base.
- */
-
- #include <stdio.h>
- #include <errno.h>
- #include "af.h"
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "defs.h"
- #include "libextern.h"
-
-
- static int islocked ;
-
-
- /*
- * Lock the data base. The data base is only locked to avoid multiple
- * writers, so the data base may be read and written simultaneously.
- */
-
- aflock() {
- char lockfile[FPATHLEN] ;
- int ntries ;
- struct stat st ;
- int fd ;
- char pid[10] ;
- long time() ;
-
- sprintf(lockfile, "%s/artfile.lck", LIB) ;
- ntries = 0 ;
- while (islocked++, (fd = creat(lockfile, 0444)) < 0) {
- islocked-- ;
- if (++ntries == 1 || ntries == 31) {
- if (stat(lockfile, &st) >= 0 && st.st_mtime < time((long *)0) - 60) {
- unlink(lockfile) ;
- continue ;
- }
- } else if (ntries > 60) {
- xerror("Can't lock data base") ;
- }
- sleep(2) ;
- }
- sprintf(pid, "%d\n", getpid()) ;
- write(fd, pid, strlen(pid)) ;
- close(fd) ;
- #ifdef notdef /* forget about stdio due to BSD bug */
- fseek(affp, 0L, 0) ;
- fread((char *)&afhd, sizeof(afhd), 1, affp) ;
- #else
- lseek(affd, 0L, 0) ;
- read(affd, (char *)&afhd, sizeof afhd) ;
- #endif
- }
-
-
- afunlock() {
- char lockfile[FPATHLEN] ;
-
- if (islocked) {
- sprintf(lockfile, "%s/artfile.lck", LIB) ;
- unlink(lockfile) ;
- islocked-- ;
- }
- }
- !E!O!F!
-
- cat > lib/afopen.c <<\!E!O!F!
- #include "defs.h"
- #include "libextern.h"
-
-
- afopen() {
- char fname[FPATHLEN] ;
-
- sprintf(fname, "%s/artfile", LIB) ;
- genafopen(fname, "r") ;
- }
- !E!O!F!
-
- cat > lib/allgroups.c <<\!E!O!F!
- #include <stdio.h>
- #include "config.h"
- #include "ng.h"
-
- char *index() ;
-
-
- nginit() {
- int c ;
-
- fseek(ngfp, 0L, 0) ;
- while ((c = getc(ngfp)) != '\n' && c != EOF) ;
- }
-
-
- ngread(g)
- register struct ngrec *g ;
- {
- char line[100] ;
- register char *p ;
-
- if (fgets(line, 100, ngfp) == NULL)
- return 0 ;
- if ((p = index(line, ' ')) == NULL)
- xerror("corrupted newsgroup file") ;
- *p++ = '\0' ;
- scopyn(line, g->g_name, sizeof(g->g_name)) ;
- g->g_num = atoi(p) ;
- g->g_flags = 0 ;
- if (index(p, 'm'))
- g->g_flags |= G_MOD ;
- return 1 ;
- }
- !E!O!F!
-
- cat > lib/artfile.h <<\!E!O!F!
- /*
- * Defines for the article data base file
- */
-
- /* flags in artrec structure */
- #define A_DUMMY 01 /* placeholder; article not yet arrived */
- #define A_EXPIRED 02 /* article has been expired */
- #define A_CANCELLED 04 /* article has been cancelled */
- #define A_NOFILE 07 /* no file for this article */
-
-
- typedef long DPTR ; /* file address */
- typedef int ARTNO ; /* article number */
- #define DNULL 0L
-
-
- #define MAXNG 5 /* max # newsgroups per article */
- #define A_MAXKW 6 /* max # keywords on an article */
- #define A_SPACE 576 /* space for storing strings */
-
-
- struct artgroup {
- short a_ngnum; /* number of this newsgroup */
- long a_artno; /* number of article within newsgroup */
- DPTR a_ngchain; /* pointer to previous article in newsgroup */
- };
-
-
- struct artrec {
- long a_subtime; /* when article was posted */
- long a_rectime; /* when article was received */
- long a_exptime; /* when this article expires (0 if not specified) */
- DPTR a_parent; /* article this is a followup to */
- DPTR a_children; /* linked list of followups */
- DPTR a_childchain; /* link for followup chain */
- DPTR a_idchain; /* chain for article id hash */
- DPTR a_titlechain; /* title hash chain */
- short a_flags; /* various flags */
- short a_nlines; /* length of article */
- char a_ngroups; /* number of newsgroups this article posted to */
- char a_nkwords; /* number of keywords on article */
- struct artgroup a_group[MAXNG]; /* list of groups article posted to */
- char *a_ident; /* message id */
- char *a_title; /* article subject line */
- char *a_from; /* author of article */
- char *a_file; /* file containing article */
- char *a_kword[A_MAXKW]; /* keywords */
- char a_space[A_SPACE]; /* space to store strings */
- };
-
-
- extern DPTR nglnext ;
-
- DPTR nglfirst() ;
- ARTNO ngltest() ;
- DPTR lookart() ;
-
-
- #define BKWD_GROUP(ngnum, artno, dp, a) for (dp = nglfirst(ngnum) ; (artno = ngltest(ngnum, &(a))) >= 0 ; dp = nglnext)
-
- #define ainit(a)
- #define afree(a)
- !E!O!F!
-
- cat > lib/arthead.h <<\!E!O!F!
- /*
- * header.h - Article header format
- */
-
- #define NUNREC 50
- #define H_SPACE 1024
- #define NHDNAME 24
-
- /* article header */
- struct arthead {
- char *h_relayversion; /* Relay-Version: */
- char *h_postversion; /* Posting-Version: */
- char *h_path; /* Path: */
- char *h_from; /* From: */
- char *h_nbuf; /* Newsgroups: */
- char *h_title; /* Subject: */
- char *h_ident; /* Message-ID: */
- char *h_subdate; /* Date: (submission) */
- char *h_oident; /* Article-I.D.: */
- char *h_postdate; /* Posted: */
- char *h_recdate; /* Date-Received: */
- char *h_expdate; /* Expires: */
- char *h_references; /* References: */
- char *h_ctlmsg; /* Control: */
- char *h_sender; /* Sender: */
- char *h_replyto; /* Reply-To: */
- char *h_followto; /* Followup-To: */
- char *h_distribution; /* Distribution: */
- char *h_organization; /* Organization: */
- char *h_numlines; /* Lines: */
- char *h_keywords; /* Keywords: */
- char *h_approved; /* Approved: */
- char *h_summary; /* Summary: */
- char *h_priority; /* Priority: */
- char *h_unrec[NUNREC]; /* unrecognized lines */
- time_t h_subtime; /* subdate in secs */
- time_t h_rectime; /* recdate in secs */
- time_t h_exptime; /* expdate in secs */
- int h_intnumlines; /* Integer version */
- int h_intpriority; /* Integer version */
- char *h_space[8]; /* string space */
- };
-
- #define hset(hdrline) ((hdrline) != NULL)
-
- FILE *gethead();
- !E!O!F!
-
- cat > lib/bcopy.c <<\!E!O!F!
- #include "config.h"
-
- #if BSDREL < 42
-
- bcopy(from, to, n)
- register char *from, *to ;
- {
- register int i ;
-
- if ((i = n) != 0) {
- do *to++ = *from++ ;
- while (--i != 0) ;
- }
- }
-
- #endif
- !E!O!F!
-
- cat > lib/bcopy.pdp <<\!E!O!F!
- / BCOPY(FROM, TO, N) CHAR *FROM, *TO ;
- /
- / Copy "n" bytes from "from" to "to".
- /
- .globl _bcopy
- .globl csav, cret
-
- .text
- _bcopy: jsr r0, csav / save registers
- mov r5, r4 / get arguments...
- cmp (r4)+, (r4)+ /
- mov (r4)+, r0 / from
- mov (r4)+, r1 / to
- mov (r4), r2 / byte count
- beq ret / if zero then return
- bit $1, r1 / is "to" odd
- beq 1f / yes...
- movb (r0)+, (r1)+ / copy one byte to make it even
- dec r2 / and adjust byte count
- 1: mov r2, r3 / save (low bit of) count
- asr r2 / convert from bytes to words
- beq 3f / if any words to copy...
- bit $1, r0 / is "from" even now?
- beq 2f / if not ...
- 1: movb (r0)+, (r1)+ / copy bytes...
- movb (r0)+, (r1)+ / ...
- sob r2, 1b / ...
- br 3f / else ...
- 2: mov (r0)+, (r1)+ / copy words...
- sob r2, 2b / ...
- 3: ror r3 / is byte count odd?
- bcc ret / if so...
- movb (r0)+, (r1)+ / copy odd byte.
- ret: jmp cret / return
- !E!O!F!
-
- cat > lib/bcopy.u3b <<\!E!O!F!
- .file "bcopy.s" # silly assembler wants this line
- .globl bcopy
- .align 4
- bcopy: save &0 # set up stack frame
- movw 0(%ap), %r0 # get source
- movw 4(%ap), %r1 # and destination
- movw 8(%ap), %r2 # get count
- movblb # this instruction does it all
- ret &0 # return
- !E!O!F!
-
- cat > lib/bcopy.vax <<\!E!O!F!
- # bcopy (from, to, count) char *from, *to; int count;
- #
- # Copy "count" bytes from "from" to "to"; not guaranteed to
- # work if "from" and "to" overlap.
-
- .align 2
- .globl _bcopy
- _bcopy:
- .word 0
- movl 4(ap), r1 # r1 = from
- movl 8(ap), r3 # r3 = to
- L1:
- movzwl $65535, r0 # while more than 65535 bytes to move
- cmpl 12(ap), r0
- jleq L2 # if <= 65535, break
- subl2 r0, 12(ap) # count-=65535 (bytes moved this time)
- movc3 r0, (r1), (r3) # r1, r3 magically point to next 65K
- brb L1
- L2:
- movc3 12(ap), (r1), (r3) # move up to 65535 bytes
- ret
- !E!O!F!
-
- cat > lib/bfr.c <<\!E!O!F!
- #include "defs.h"
-
- char bfr[LBUFLEN]; /* general purpose buffer */
- !E!O!F!
-
- cat > lib/bzero.c <<\!E!O!F!
- /*
- * Set nc bytes, starting at cp, to zero.
- */
-
- #include "config.h"
-
- #if BSDREL < 42
-
- bzero(cp, nc)
- register char *cp;
- register int nc;
- {
- while (--nc >= 0)
- *cp++ = 0;
- }
-
- #endif
- !E!O!F!
-
- cat > lib/bzero.pdp <<\!E!O!F!
- / BZERO(MEM, N) CHAR *MEM;
- /
- / Clear "n" bytes of memory starting at "mem".
- /
- .globl _bzero
- .globl csav, cret
-
- .text
- _bzero: jsr r0, csav / save registers
- mov 4(r5), r0 / get memory pointer...
- mov 6(r5), r1 / ...and count
- beq ret / return if zero
- bit $1, r0 / is address odd?
- beq 1f / yes...
- clrb (r0)+ / clear one byte to make it even
- dec r1 / and adjust byte count
- 1: mov r1, r3 / save (low bit of) count
- clr r2 / get zero into a register and clear carry
- ror r1 / convert count to words.
- asr r1 / convert count to double words
- bcc 1f / if word count was odd
- mov r2, (r0)+ / clear an extra word
- tst r1 / reset condition codes on r1
- 1: beq 3f / while r1 ~= 0
- 2: mov r2, (r0)+ / clear a word...
- mov r2, (r0)+ /
- sob r1, 2b / and update count
- 3: asr r3 / if count was odd
- bcc ret /
- movb r2, (r0)+ / clear an extra byte
- ret: jmp cret / return
- !E!O!F!
-
- cat > lib/bzero.u3b <<\!E!O!F!
- .file "bzero.u3b" # assembler wants this
-
- # This code relies on the fact that bzero(mem, n) is equivalent to
- # strncpy("", mem, n).
-
- .globl bzero
- .align 4
- bzero: save &1 # set up stack frame and save r8
- movw 0(%ap), %r0 # get address
- movw 4(%ap), %r1 # and count
- movw &0, %r2 # various parameters are zero
- movaw zero, %r8 # null string
- movccep %r8,%r1,%r0,%r2,%r2 # strncpy insruction
- ret &1 # return
-
- .data
- zero: .byte 0
- !E!O!F!
-
- cat > lib/cancel.c <<\!E!O!F!
- /*
- * Cancel the article whose header is in hp, by posting a control message
- * to cancel it. The scope of the control message depends on who would
- * really be willing to cancel it. It is sent as far as it will do any good.
- * notauthor is true iff the person posting this article is not the
- * real author of the article being cancelled.
- */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include "config.h"
- #include "arthead.h"
- #include "libextern.h"
-
- cancel(ofp, hp, notauthor)
- FILE *ofp;
- struct arthead *hp;
- int notauthor;
- {
- FILE *inews;
- char distgroup[64];
- int pid;
- char bfr[512];
- char *index();
- FILE *popen();
-
- /* fflush(stdout); */
- pid = fork();
- if (pid > 0)
- return 0;
- strcpy(distgroup, hp->h_nbuf);
- if (notauthor)
- sprintf(distgroup, "to.%s", FULLSYSNAME);
- else
- sprintf(distgroup, "%s", hp->h_nbuf);
- sprintf(bfr, "%s -t 'cmsg cancel %s' -n %s < /dev/null",
- XINEWS, hp->h_ident, distgroup);
- if ((inews = popen(bfr, "w")) == NULL)
- fprintf(ofp, "Can't fork %s\n", XINEWS);
- else
- pclose(inews);
- if (pid == 0)
- _exit(0);
- return 0;
- }
- !E!O!F!
-
- cat > lib/cgtdate.c <<\!E!O!F!
- #include <stdio.h>
- #include <sys/types.h>
- #include "config.h"
- #ifndef BSDREL >= 7
- #include <sys/timeb.h>
- #else
- struct timeb
- {
- time_t time;
- unsigned short millitm;
- short timezone;
- short dstflag;
- };
- #endif
-
- time_t getdate();
- long getadate();
-
-
- time_t
- cgtdate(datestr)
- char *datestr;
- {
- time_t i;
- char junk[40],month[40],day[30],time[60],year[50];
- char bfr[181];
-
- if ((i = getadate(datestr)) != -1L)
- return i;
- if ((i = getdate(datestr, (struct timeb *) NULL)) >= 0)
- return i;
- sscanf(datestr, "%s %s %s %s %s", junk, month, day, time, year);
- sprintf(bfr, "%s %s, %s %s", month, day, year, time);
- return getdate(bfr, (struct timeb *) NULL);
- }
- !E!O!F!
-
- cat > lib/cgtdatecmd.c <<\!E!O!F!
- /*
- * This program takes a date as its argument and writes the UN*X internal
- * value on the standard output. The primary purpose of this program is
- * to make it unnecessary to load the cgtdate routine as part of readnews
- * and/or vnews.
- */
-
- #include <stdio.h>
-
- main(argc, argv)
- char **argv ;
- {
- char buf[1024] ;
- register int i ;
- long tim ;
- long cgtdate() ;
-
- buf[0] = '\0' ;
- for (i = 1 ; i < argc ; i++) {
- strcat(buf, " ") ;
- strcat(buf, argv[i]) ;
- }
- tim = cgtdate(buf) ;
- if (tim == -1L)
- return 1 ;
- printf("%ld\n", tim) ;
- return 0 ;
- }
- !E!O!F!
-
- cat > lib/ckfopen.c <<\!E!O!F!
- /*
- * Open file, calling xerror on failure.
- */
-
- #include <stdio.h>
- #include "config.h"
-
- FILE *
- ckfopen(name, mode)
- register char *name, *mode;
- {
- register FILE *fp;
- extern int errno;
-
- if ((fp = fopen(name, mode)) == NULL) {
- #ifdef IHCC
- char *fname, *rindex();
- /*
- * IHCC users only see the "filename" that was in trouble,
- * not the whole path. (for security!)
- */
- if ((fname = rindex(name, '/') != NULL)
- fname++;
- else
- fname = name;
- xerror("Cannot open %s (%s), errno=%d", fname, mode, errno);
- #else
- xerror("Cannot open %s (%s), errno=%d", name, mode, errno);
- #endif
- }
- #ifdef notdef /* this doesn't make sense for readnews */
- /* kludge for setuid not being honored for root */
- if ((uid == 0) && (duid != 0) && ((mode == "a") || (mode == "w")))
- chown(name, duid, dgid);
- #endif
- return(fp);
- }
- !E!O!F!
-
- cat > lib/ckmalloc.c <<\!E!O!F!
- char *
- ckmalloc(nbytes)
- unsigned nbytes ;
- {
- register char *p ;
- char *malloc() ;
-
- if ((p = malloc(nbytes)) == (char *)0)
- xerror("out of space") ;
- return p ;
- }
- !E!O!F!
-
- cat > lib/config.hou3c <<\!E!O!F!
- # This is the config file I use on hou3c.
-
- newsusr netnews
- newsgrp other
- myorg AT&T Bell Labs, Holmdel
- mydomain .UUCP
- path /bin:/usr/bin:/usr/lbin
- spool /tools/netnews/spool
- admin ka
- notify
- admsub
- !E!O!F!
-
- cat > lib/config.sample <<\!E!O!F!
- #This is a sample config file (with more comments than a real config file
- #would contain, of course). First, we list all the possible entries.
- #
- #Lines in the setup file consist of a name followed by a value. The various
- #types of values are string, indicated by "str", integer, indicated by "int",
- #and boolean, indicated by "bool". The default value, if any, is indicated
- #by DFT. In certain cases, there is a default which is assigned when a null
- #value is given for the value. If the value is boolean, the default is "yes",
- #other defaults for null values are indicated by NDFT.
- #
- #
- #NAME TYPE DESCRTIPTION
- #admin str Netnews administrator. (DFT is your login name)
- #admsub str Mandatory subscription list. DFT general,all.announce
- #bin str Directory where programs (e. g. inews) placed. DFT /usr/bin
- #buflen int Length of various bufs. DFT 128 if small, else 256
- #compadmin bool Recompute the numeric admin id each time program run. DFT no
- #datelen int Max length of date. DFT 48
- #dfteditor str Default editor program. DFT /bin/ed
- #dftexp int Default expiration time in days. DFT 14
- #dftsub str Default subscription list. DFT all
- #fpathlen int Max length of file path name. DFT 64
- #ghname bool True if system has gethostname call. DFT yes if 4.2bsd.
- #home str Lib and spool are relative to this user's home directory.
- #internet bool True if mailer understands internet addresses. DFT yes
- #lbuflen int Length of large buffer. DFT 1024
- #lib str Directory for misc netnews files. DFT /usr/lib/news
- #mailer str Mail program. DFT /bin/mail
- #manually bool Require that admin remove groups manually. DFT yes
- #maxgroups int Maximum number of newsgroups.
- #mydomain str Appended to sys name to get domain name. This entry mandatory.
- #myname str System name. Computed at run time if omitted.
- #myorg str Organization name. This entry mandatory.
- #namelen int Max length of internet address or messge ID. DFT 64
- #newsgrp str Group of news software. This entry is mandatory.
- #newsrc str Name of newsrc file. DFT .newsrc
- #newsusr str Owner of news software. This entry is mandatory.
- #notify str Inform person about certain control messages. NDFT admin
- #page str Pager program. NDFT /usr/ucb/more
- #path str Path use by setup to find various programs. DFT $PATH
- #pathlen int Max length of return path. DFT 512
- #small bool True if 16 bit address space. DFT yes if on pdp11.
- #spool str Directory where articles stored. DFT /usr/spool/news
- #sys str Operating system version. (Guessed by default)
- #termcap str Name of termcap library. (Guessed by default)
- #tmail str Mailer that understands -t option. NDFT /usr/lib/sendmail
- #umask int Umask value; use 022 for secure system. DFT 000
- #uname bool True if system has uname system call. DFT yes if USG system.
- #v7mail bool True if use Version 7 mail format. DFT yes
-
-
- # OK, now to give our config entries.
- # First we give the required ones.
-
- # The login and group owning the netnews software.
- newsusr netnews
- newsgrp other
-
- # The name of my organization.
- myorg AT&T Bell Labs, Holmdel
-
- # My domain.
- mydomain .UUCP
-
- # The remaining entries are not required by the setup program.
-
- # Use a standard path for the rest of setup
- path /bin:/usr/bin:/usr/lbin
-
- # We don't have room in the /usr file system for the spool directory,
- # so we place it elsewhere.
- spool /tools/netnews/spool
-
- # Since I am running the setup program, this is unnecessary, but it is
- # safer to include it in case somebody else recompiles the news software
- # for some reason
- admin ka
-
- # I want to be told about create and rmgrp control messages. Since I am
- # the person running the config program, they will be sent to me by default.
- notify
-
- # Mandatory subscripts are fascist, so no mandatory subscriptions on hou3c.
- admsub
-
- # End of sample config file.
- !E!O!F!
-
- cat > lib/cpu.c <<\!E!O!F!
- /* This file is run through cpp to determine the cpu type */
- #ifdef pdp11
- Xpdp11
- #endif
- #ifdef vax
- Xvax
- #endif
- #ifdef u3b
- Xu3b
- #endif
- !E!O!F!
-
- cat > lib/defs.h <<\!E!O!F!
- /*
- * defs.h - defines for news-related programs.
- *
- * By convention, the version of the software you are running is taken
- * to be news_version below.
- */
-
- #define news_version "B 2.11-B 1/17/84"
- /* SCCS ID @(#)defs.dist 2.23 5/3/83 */
-
- #include "newsdefs.h" /* this gets most of the definitions */
-
- #define FOLLOWUP INEWS
- #define NEWSRC ".newsrc"
- /* #define BERKNAME "ARPAVAX" /* name of local host on Berknet */
-
- #define LINES 512 /* maximum no. of lines in .newsrc */
- #define NEGCHAR '!' /* newsgroup negation character */
- #define DEADTIME 45 /* no. of seconds to wait on deadlock */
- #define FMETA '%' /* file meta-character for c option */
- #define SYSPATH "PATH=/local/bin:/bin:/usr/bin" /* default, secure, vanilla path */
- #define LNCNT 16 /* Articles with > LNCNT lines go through pager */
-
- /* Things you probably won't want to change */
- #define SNLN 8 /* max significant characters in sysname */
- #define PROTO 'A' /* old protocol name */
- #define NETCHRS "!:.@^%"/* Punct. chars used for various networks */
- #define TRUE 1 /* boolean true */
- #define FALSE 0 /* boolean false */
- #define NGFSIZ 5000 /* legal newsgroup file size */
- #define NGDELIM ',' /* delimit character in news group line */
- !E!O!F!
-
- cat > lib/dir.c <<\!E!O!F!
- #include "config.h"
- #if BSDREL < 42
- #include <sys/types.h>
- #include <sys/param.h>
- #include "ndir.h"
-
- /*
- * open a directory.
- */
- DIR *
- opendir(name)
- char *name;
- {
- register DIR *dirp;
- register int fd;
- char *malloc();
-
- if ((fd = open(name, 0)) == -1)
- return NULL;
- if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
- close (fd);
- return NULL;
- }
- dirp->dd_fd = fd;
- dirp->dd_nleft = 0;
- return dirp;
- }
-
-
-
- /*
- * close a directory.
- */
- void
- closedir(dirp)
- register DIR *dirp;
- {
- close(dirp->dd_fd);
- free(dirp);
- }
-
-
-
- /*
- * read an old style directory entry and present it as a new one
- */
- #define ODIRSIZ 14
-
- struct olddirect {
- ino_t od_ino;
- char od_name[ODIRSIZ];
- };
-
- /*
- * get next entry in a directory.
- */
- struct direct *
- readdir(dirp)
- register DIR *dirp;
- {
- register struct olddirect *dp;
- static struct direct dir;
-
- for (;;) {
- if ((dirp->dd_nleft -= sizeof(struct olddirect)) < 0) {
- dirp->dd_nleft = read(dirp->dd_fd, dirp->dd_buf,
- DIRBLKSIZ);
- if (dirp->dd_nleft <= 0)
- return NULL;
- dirp->dd_nextc = dirp->dd_buf;
- }
- dp = (struct olddirect *) dirp->dd_nextc;
- dirp->dd_nextc += sizeof(struct olddirect);
- if (dp->od_ino == 0)
- continue;
- dir.d_ino = dp->od_ino;
- strncpy(dir.d_name, dp->od_name, ODIRSIZ + 1);
- dir.d_namlen = strlen(dir.d_name);
- return (&dir);
- }
- }
- #endif
- !E!O!F!
-
- cat > lib/dirname.c <<\!E!O!F!
- #include "defs.h"
- #include "libextern.h"
-
-
- char *
- dirname(ngname, rbuf)
- char *ngname;
- char rbuf[FPATHLEN];
- {
- register char *p;
-
- sprintf(rbuf, "%s/%s", SPOOL, ngname);
- for (p=rbuf+strlen(SPOOL); *p; p++)
- if (*p == '.')
- *p = '/';
- return rbuf;
- }
- !E!O!F!
-
- cat > lib/doc.h <<\!E!O!F!
- .na
- Newsgroups may be refered to by name or my number.
- The name is identical across all machines,
- the number is specific to a particular machine.
-
- Articles are refered to by message id, by number in newsgroup,
- or by offset into data base.
- The message id is the same on all machines.
- The number is specific to a given machine.
- The offset into the data base is specific to a particular
- machine and a particular open call to the data base.
- (When expire runs, it moves the article records.
- A program which has the data base open will continue
- to use the old data base, however, so that the same offsets
- will still work.)
-
- The article data base contains a record for each article.
- It consists of a single file divided into several sections.
- First is the header, which gives the size of the other sections.
- Second is a hash table for message ids.
- Third is a hash table of reference lines which is used to deal with
- orphaned articles.
- Fourth is a table of pointers to newsgroup chains.
- All the articles in a newsgroup are connected by a singly linked list.
- Finally, the article records appear.
-
- There is one article record for each article.
- !E!O!F!
-
- cat > lib/findgroup.c <<\!E!O!F!
- #include "defs.h"
- #include "str.h"
- #include "newsrc.h"
-
-
- struct ngentry *
- findgroup(name)
- register char *name ;
- {
- register struct ngentry *ngp ;
- extern int maxng ;
-
- for (ngp = ngtable; ngp < ngtable + MAXGROUPS ; ngp++) {
- if (ngp->ng_name && equal(ngp->ng_name, name))
- return ngp ;
- }
- return 0 ;
- }
- !E!O!F!
-
- cat > lib/ftime.c <<\!E!O!F!
- #include "config.h"
-
- #if BSDREL < 7
- static char *SccsId = "@(#)ftime.c 2.3 3/3/83";
-
- #include <sys/types.h>
- struct timeb
- {
- time_t time;
- unsigned short millitm;
- short timezone;
- short dstflag;
- };
-
- extern long timezone;
- extern int daylight;
-
- ftime(tp)
- struct timeb *tp;
- {
- long t;
-
- tzset(); /* be sure time zone info set */
- time(&t);
- tp->time = t;
- tp->millitm = 0;
- tp->timezone = timezone/60;
- tp->dstflag = daylight;
- }
- #endif
- !E!O!F!
-
- cat > lib/genafopen.c <<\!E!O!F!
- #include <stdio.h>
- #include "af.h"
-
-
- int affd ; /* artfile file descriptor */
- struct afheader afhd ; /* artfile header */
-
-
- genafopen(file, mode)
- char *file, *mode ;
- {
- int omode = mode[1] ? 2 : 0 ;
-
- if ((affd = open(file, omode)) < 0
- && (sleep(2), affd = open(file, omode)) < 0)
- xerror("can't open %s", file) ;
- if (read(affd, (char *)&afhd, sizeof(afhd)) != sizeof afhd)
- xerror("can't read data base header") ;
- if (afhd.af_magic != AF_MAGIC)
- xerror("bad data base file") ;
- if (afhd.af_version != AF_VERSION)
- xerror("Version of article data base is wrong") ;
- }
- !E!O!F!
-
- cat > lib/genmakefile <<\!E!O!F!
- . makedefs
- exec > makefile
- cat <<\!
- # makefile for rlib 1/4/85
-
- !
- cat makedefs
- cat <<\!
-
- CFLAGS = $(DEBUG)
- DEBUG = -O
- MAKE = make
-
- RLIB = aflock.o afopen.o cancel.o cgtdate.o dir.o dirname.o\
- genafopen.o getadate.o getdate.o ftime.o gethead.o getopt.o\
- getuser.o hfgets.o hfree.o hxchg.o isadmin.o isre.o launder.o\
- lookup.o ngchain.o ngmatch.o openrc.o pgetuser.o read.o\
- replyname.o rewinddir.o rmnf.o readinrc.o roptions.o titmat.o\
- write.o setupgrp.o addrc.o allgroups.o findgroup.o gfopen.o\
- makehimask.o nextgrp.o prevgrp.o bfr.o bcopy.o bzero.o ckfopen.o\
- getaddr.o hash.o lcase.o nsavestr.o nstrip.o prefix.o process.o\
- rename.o savestr.o ckmalloc.o scopyn.o strpbrk.o strcspn.o\
- strspn.o strtok.o tomsgid.o
-
-
- all: setuptime makefile rlib.a cgtdate rpathinit.o newer
-
- install: all
- /bin/cp cgtdate $(LIBDIR)/cgtdate
-
- setuptime: setup config
- sh setup
-
- makefile: genmakefile makedefs
- genmakefile
- @echo 'Makefile changed. Restart make program.'
- @sh -c 'exit 22'
-
- rlib.a: $(RLIB)
- rm -f $@
- ar rc $@ $(RLIB)
- !
- if test $BSDREL -gt 7
- then echo " ranlib \$@"
- fi
- : Add more assembly language routines when they have been tested.
- case $CPU in
- pdp11) files="" suffix=pdp ;;
- vax) files="scopyn" suffix=vax ;;
- u3b) files="bcopy bzero scopyn strpbrk" suffix=u3b ;;
- *) files=
- esac
- for x in $files
- do cat <<!
-
- $x.o: $x.$suffix
- \$(AS) -o $x.o $x.$suffix
- !
- done
- cat <<\!
-
- rpathinit.o: mypathinit.c defs.h newsdefs.h $(FRC)
- $(CC) -c $(CFLAGS) mypathinit.c
- mv mypathinit.o rpathinit.o
-
- genafopen.o lock.o lookup.o ngchain.o read.o: af.h artfile.h
- readinrc.o setupgrp.o: artfile.h
- addrc.o nextgrp.o prevgrp.o readinrc.o setupgrp.o: newsrc.h
- allgroups.o readinrc.o: ng.h
- cancel.o gethead.o hfree.o hxchg.o: arthead.h
- $(RLIB): $(FRC)
-
- cgtdate: cgtdatecmd.o cgtdate.o getadate.o getdate.o
- $(CC) $(LFLAGS) -o $@ cgtdatecmd.o rlib.a
-
- newer: newer.c
- $(CC) -o $@ newer.c
-
- FRC:
- !
- !E!O!F!
- chmod +x lib/genmakefile
-
- cat > lib/getadate.c <<\!E!O!F!
- /*
- * getadate - get arpa date.
- *
- * This routine takes a character character string containing a
- * date-time in the format specified in RFC 822 and converts it
- * to UNIX internal format. The components of the date are left
- * in the global tm structure arpadtm. Getarpad returns -1L if
- * the argument is syntactically incorrect.
- */
-
- #include "config.h"
- #if BSDREL == 42
- #include <sys/time.h>
- #else
- #include <time.h>
- #endif
- #include <ctype.h>
-
- #define HR 3600
- #define DAY (24L*HR)
-
- struct tm adatetm ;
-
- static int lookup(), getdig(), skipbl() ;
- static char *d ;
- static char *days[] = {"sun", "mon", "tue", "wed", "thu", "fri", "sat", 0} ;
- static char *months[] = {"jan", "feb", "mar", "apr", "may", "jun",
- "jul", "aug", "sep", "oct", "nov", "dec", 0} ;
- static char *zones[] =
- {"ut", "gmt", "est", "edt", "cst", "cdt", "mst", "mdt", "pst", "pdt",
- "a", "b", "c", "d", "e", "f", "g", "h", "i", "k", "l", "m",
- "n", "o", "p", "q", "r", "s",
- "t", "u", "v", "w", "x", "y", "z",
- /* the remaining time zones are not legal according to RFC822 */
- "yst", "ydt", "hst", "hdt",
- "aest", "aesst", "acst", "acsst", "awst", 0} ;
- static long zoffset[] =
- {0, 0, 5*HR, 4*HR, 6*HR, 5*HR, 7*HR, 6*HR, 8*HR, 7*HR,
- 1*HR,2*HR,3*HR,4*HR,5*HR,6*HR,7*HR,8*HR,9*HR,10*HR,11*HR,12*HR,
- -1*HR, -2*HR, -3*HR, -4*HR, -5*HR, -6*HR,
- -7*HR, -8*HR, -9*HR,-10*HR,-11*HR,-12*HR, 0,
- /* the remaining time zones are not legal according to RFC822 */
- 9*HR, 8*HR, 10*HR, 9*HR,
- -10*HR, -11*HR, -9*HR-HR/2,-10*HR-HR/2,-8*HR, 0} ;
- static int mon[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334} ;
-
-
- long
- getadate(date)
- register char *date ;
- {
- int i ;
- int oh ;
- long tim ;
- long offset ;
-
- d = date ;
- if ((adatetm.tm_wday = lookup(days)) >= 0) {
- if (getch(',') < 0)
- bad: return -1L ;
- }
- skipbl() ;
- if (! isdigit(*d))
- goto bad ;
- adatetm.tm_mday = *d++ - '0' ;
- if (isdigit(*d))
- adatetm.tm_mday = adatetm.tm_mday * 10 + *d++ - '0' ;
- if (*d == '-') /* ARPA spec doesn't permit this */
- d++ ;
- if ((adatetm.tm_mon = lookup(months)) < 0)
- goto bad ;
- getch('-') ; /* ARPA spec doesn't permit this */
- if ((adatetm.tm_year = getdig()) < 0)
- goto bad ;
- skipbl() ;
- if ((adatetm.tm_hour = getdig()) < 0)
- goto bad ;
- if (getch(':') < 0)
- goto bad ;
- if ((adatetm.tm_min = getdig()) < 0)
- goto bad ;
- if (getch(':') < 0)
- adatetm.tm_sec = 0 ;
- else if ((adatetm.tm_sec = getdig()) < 0)
- goto bad ;
- if (getch('+') >= 0) {
- offset = 60 ;
- numtz: if ((oh = getdig()) < 0
- || (i = getdig()) < 0)
- goto bad ;
- offset *= 60 * oh + i ;
- } else if (getch('-') >= 0) {
- offset = -60 ;
- goto numtz ;
- } else if ((i = lookup(zones)) >= 0)
- offset = zoffset[i] ;
- else
- goto bad ;
-
- /* now calculate the time */
- adatetm.tm_yday = mon[adatetm.tm_mon] + adatetm.tm_mday - 1 ;
- if ((adatetm.tm_year & 03) == 0 && adatetm.tm_mon >= 2)
- adatetm.tm_yday++ ;
- tim = adatetm.tm_sec + 60 * adatetm.tm_min + 3600L * adatetm.tm_hour
- + offset + DAY * adatetm.tm_yday ;
- for (i = adatetm.tm_year ; --i >= 70 ; )
- tim += (i & 03) == 0? 366 * DAY : 365 * DAY ;
- return tim ;
- }
-
-
-
- static int
- lookup(ltab)
- char **ltab ;
- {
- char tok[20] ;
- register char *dp ;
- register char *tp ;
- register char **lp ;
-
- dp = d ;
- tp = tok ;
- while (isspace(*dp))
- dp++ ;
- for (;;) {
- if (isupper(*dp))
- *tp++ = tolower(*dp) ;
- else if (islower(*dp))
- *tp++ = *dp ;
- else
- break ;
- if (tp >= &tok[20])
- return -1 ;
- dp++ ;
- }
- if (dp == d)
- return -1 ;
- *tp = '\0' ;
- for (lp = ltab ; *lp ; lp++) {
- if (strcmp(*lp, tok) == 0) {
- d = dp ;
- return lp - ltab ;
- }
- }
- return -1 ;
- }
-
-
- static int
- getdig() {
- register char *p ;
-
- p = d ;
- if (! isdigit(*p) || ! isdigit(*++p))
- return -1 ;
- d += 2 ;
- return 10 * p[-1] + p[0] - (10 * '0' + '0') ;
- }
-
-
- static
- skipbl() {
- while (isspace(*d))
- d++ ;
- }
-
-
- static int
- getch(c) {
- skipbl() ;
- if (*d != c)
- return -1 ;
- d++ ;
- skipbl() ;
- return 0 ;
- }
- !E!O!F!
-
- cat > lib/getaddr.c <<\!E!O!F!
- /*
- * Get the machine address of a person, stripping off the real name.
- */
-
- #include <stdio.h>
- #include "config.h"
- #include "defs.h"
-
- char *
- getaddr(full, mach)
- char full[] ;
- char mach[NAMELEN] ;
- {
- register char *p, *q, *r ;
- char *index(), *rindex();
-
- p = full ;
- if ((q = index(p, '(')) == NULL)
- q = p + strlen(p) ;
- if ((p = index(full, '<')) != NULL && p < q && (r = rindex(p, '>')) != NULL) {
- p++ ;
- q = r ;
- } else
- p = full ;
- while (*p == ' ')
- p++ ;
- while (--q > p && *q == ' ') ;
- if (q > p + NAMELEN - 1)
- q = p + NAMELEN - 1 ;
- r = mach ;
- while (p <= q)
- *r++ = *p++ ;
- *r = '\0' ;
- return mach ;
- }
- !E!O!F!
-
- cat > lib/getdate.y <<\!E!O!F!
- %token ID MONTH DAY MERIDIAN NUMBER UNIT MUNIT SUNIT ZONE DAYZONE AGO
- %{
- /* Steven M. Bellovin (unc!smb) */
- /* Dept. of Computer Science */
- /* University of North Carolina at Chapel Hill */
- /* @(#)getdate.y 2.6 4/20/84 */
-
- #include <sys/types.h>
- #include "config.h"
- #if BSDREL < 7
- struct timeb
- {
- time_t time;
- unsigned short millitm;
- short timezone;
- short dstflag;
- };
- #else
- #include <sys/timeb.h>
- #endif
- #include <ctype.h>
- #include <time.h>
-
- #define NULL 0
- #define daysec (24L*60L*60L)
- static int timeflag, zoneflag, dateflag, dayflag, relflag;
- static time_t relsec, relmonth;
- static int hh, mm, ss, merid, daylight;
- static int dayord, dayreq;
- static int month, day, year;
- static int ourzone;
- #define AM 1
- #define PM 2
- #define DAYLIGHT 1
- #define STANDARD 2
- #define MAYBE 3
- %}
-
- %%
- timedate: /* empty */
- | timedate item;
-
- item: tspec =
- {timeflag++;}
- | zone =
- {zoneflag++;}
- | dtspec =
- {dateflag++;}
- | dyspec =
- {dayflag++;}
- | rspec =
- {relflag++;}
- | nspec;
-
- nspec: NUMBER =
- {if (timeflag && dateflag && !relflag) year = $1;
- else {timeflag++;hh = $1/100;mm = $1%100;ss = 0;merid = 24;}};
-
- tspec: NUMBER MERIDIAN =
- {hh = $1; mm = 0; ss = 0; merid = $2;}
- | NUMBER ':' NUMBER =
- {hh = $1; mm = $3; merid = 24;}
- | NUMBER ':' NUMBER MERIDIAN =
- {hh = $1; mm = $3; merid = $4;}
- | NUMBER ':' NUMBER ':' NUMBER =
- {hh = $1; mm = $3; ss = $5; merid = 24;}
- | NUMBER ':' NUMBER ':' NUMBER MERIDIAN =
- {hh = $1; mm = $3; ss = $5; merid = $6;};
-
- zone: ZONE =
- {ourzone = $1; daylight = STANDARD;}
- | DAYZONE =
- {ourzone = $1; daylight = DAYLIGHT;};
-
- dyspec: DAY =
- {dayord = 1; dayreq = $1;}
- | DAY ',' =
- {dayord = 1; dayreq = $1;}
- | NUMBER DAY =
- {dayord = $1; dayreq = $2;};
-
- dtspec: NUMBER '/' NUMBER =
- {month = $1; day = $3;}
- | NUMBER '/' NUMBER '/' NUMBER =
- {month = $1; day = $3; year = $5;}
- | MONTH NUMBER =
- {month = $1; day = $2;}
- | MONTH NUMBER ',' NUMBER =
- {month = $1; day = $2; year = $4;}
- | NUMBER MONTH =
- {month = $2; day = $1;}
- | NUMBER MONTH NUMBER =
- {month = $2; day = $1; year = $3;};
-
-
- rspec: NUMBER UNIT =
- {relsec += 60L * $1 * $2;}
- | NUMBER MUNIT =
- {relmonth += $1 * $2;}
- | NUMBER SUNIT =
- {relsec += $1;}
- | UNIT =
- {relsec += 60L * $1;}
- | MUNIT =
- {relmonth += $1;}
- | SUNIT =
- {relsec++;}
- | rspec AGO =
- {relsec = -relsec; relmonth = -relmonth;};
- %%
-
- static int mdays[12] =
- {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- #define epoch 1970
-
- extern struct tm *localtime();
- time_t dateconv(mm, dd, yy, h, m, s, mer, zone, dayflag)
- int mm, dd, yy, h, m, s, mer, zone, dayflag;
- {
- time_t tod, jdate;
- register int i;
- time_t timeconv();
-
- if (yy < 0) yy = -yy;
- if (yy < 100) yy += 1900;
- mdays[1] = 28 + (yy%4 == 0);
- if (yy < epoch || yy > 1999 || mm < 1 || mm > 12 ||
- dd < 1 || dd > mdays[--mm]) return (-1);
- jdate = dd-1;
- for (i=0; i<mm; i++) jdate += mdays[i];
- for (i = epoch; i < yy; i++) jdate += 365 + (i%4 == 0);
- jdate *= daysec;
- jdate += zone * 60L;
- if ((tod = timeconv(h, m, s, mer)) < 0) return (-1);
- jdate += tod;
- if (dayflag==DAYLIGHT || (dayflag==MAYBE&&localtime(&jdate)->tm_isdst))
- jdate += -1*60*60;
- return (jdate);
- }
-
- time_t dayconv(ord, day, now) int ord, day; time_t now;
- {
- register struct tm *loctime;
- time_t tod;
- time_t daylcorr();
-
- tod = now;
- loctime = localtime(&tod);
- tod += daysec * ((day - loctime->tm_wday + 7) % 7);
- tod += 7*daysec*(ord<=0?ord:ord-1);
- return daylcorr(tod, now);
- }
-
- time_t timeconv(hh, mm, ss, mer) register int hh, mm, ss, mer;
- {
- if (mm < 0 || mm > 59 || ss < 0 || ss > 59) return (-1);
- switch (mer) {
- case AM: if (hh < 1 || hh > 12) return(-1);
- return (60L * ((hh%12)*60L + mm)+ss);
- case PM: if (hh < 1 || hh > 12) return(-1);
- return (60L * ((hh%12 +12)*60L + mm)+ss);
- case 24: if (hh < 0 || hh > 23) return (-1);
- return (60L * (hh*60L + mm)+ss);
- default: return (-1);
- }
- }
- time_t monthadd(sdate, relmonth) time_t sdate, relmonth;
- {
- struct tm *ltime;
- time_t dateconv();
- time_t daylcorr();
- int mm, yy;
-
- if (relmonth == 0) return 0;
- ltime = localtime(&sdate);
- mm = 12*ltime->tm_year + ltime->tm_mon + relmonth;
- yy = mm/12;
- mm = mm%12 + 1;
- return daylcorr(dateconv(mm, ltime->tm_mday, yy, ltime->tm_hour,
- ltime->tm_min, ltime->tm_sec, 24, ourzone, MAYBE), sdate);
- }
-
- time_t daylcorr(future, now) time_t future, now;
- {
- int fdayl, nowdayl;
-
- nowdayl = (localtime(&now)->tm_hour+1) % 24;
- fdayl = (localtime(&future)->tm_hour+1) % 24;
- return (future-now) + 60L*60L*(nowdayl-fdayl);
- }
-
- static char *lptr;
-
- yylex()
- {
- extern int yylval;
- int sign;
- register char c;
- register char *p;
- char idbuf[20];
- int pcnt;
-
- for (;;) {
- while (isspace(*lptr)) lptr++;
-
- if (isdigit(c = *lptr) || c == '-' || c == '+') {
- if (c== '-' || c == '+') {
- if (c=='-') sign = -1;
- else sign = 1;
- if (!isdigit(*++lptr)) {
- /* yylval = sign; return (NUMBER); */
- return yylex(); /* skip the '-' sign */
- }
- } else sign = 1;
- yylval = 0;
- while (isdigit(c = *lptr++)) yylval = 10*yylval + c - '0';
- yylval *= sign;
- lptr--;
- return (NUMBER);
-
- } else if (isalpha(c)) {
- p = idbuf;
- while (isalpha(c = *lptr++) || c=='.')
- *p++ = c;
- *p = '\0';
- lptr--;
- return (lookup(idbuf));
- }
-
- else if (c == '(') {
- pcnt = 0;
- do {
- c = *lptr++;
- if (c == '\0') return(c);
- else if (c == '(') pcnt++;
- else if (c == ')') pcnt--;
- } while (pcnt > 0);
- }
-
- else return (*lptr++);
- }
- }
-
- struct table {
- char *name;
- int type, value;
- };
-
- struct table mdtab[] = {
- {"January", MONTH, 1},
- {"February", MONTH, 2},
- {"March", MONTH, 3},
- {"April", MONTH, 4},
- {"May", MONTH, 5},
- {"June", MONTH, 6},
- {"July", MONTH, 7},
- {"August", MONTH, 8},
- {"September", MONTH, 9},
- {"Sept", MONTH, 9},
- {"October", MONTH, 10},
- {"November", MONTH, 11},
- {"December", MONTH, 12},
-
- {"Sunday", DAY, 0},
- {"Monday", DAY, 1},
- {"Tuesday", DAY, 2},
- {"Tues", DAY, 2},
- {"Wednesday", DAY, 3},
- {"Wednes", DAY, 3},
- {"Thursday", DAY, 4},
- {"Thur", DAY, 4},
- {"Thurs", DAY, 4},
- {"Friday", DAY, 5},
- {"Saturday", DAY, 6},
- {0, 0, 0}};
-
- #define HRS *60
- #define HALFHR 30
- struct table mztab[] = {
- {"a.m.", MERIDIAN, AM},
- {"am", MERIDIAN, AM},
- {"p.m.", MERIDIAN, PM},
- {"pm", MERIDIAN, PM},
- {"nst", ZONE, 3 HRS + HALFHR}, /* Newfoundland */
- {"n.s.t.", ZONE, 3 HRS + HALFHR},
- {"ast", ZONE, 4 HRS}, /* Atlantic */
- {"a.s.t.", ZONE, 4 HRS},
- {"adt", DAYZONE, 4 HRS},
- {"a.d.t.", DAYZONE, 4 HRS},
- {"est", ZONE, 5 HRS}, /* Eastern */
- {"e.s.t.", ZONE, 5 HRS},
- {"edt", DAYZONE, 5 HRS},
- {"e.d.t.", DAYZONE, 5 HRS},
- {"cst", ZONE, 6 HRS}, /* Central */
- {"c.s.t.", ZONE, 6 HRS},
- {"cdt", DAYZONE, 6 HRS},
- {"c.d.t.", DAYZONE, 6 HRS},
- {"mst", ZONE, 7 HRS}, /* Mountain */
- {"m.s.t.", ZONE, 7 HRS},
- {"mdt", DAYZONE, 7 HRS},
- {"m.d.t.", DAYZONE, 7 HRS},
- {"pst", ZONE, 8 HRS}, /* Pacific */
- {"p.s.t.", ZONE, 8 HRS},
- {"pdt", DAYZONE, 8 HRS},
- {"p.d.t.", DAYZONE, 8 HRS},
- {"yst", ZONE, 9 HRS}, /* Yukon */
- {"y.s.t.", ZONE, 9 HRS},
- {"ydt", DAYZONE, 9 HRS},
- {"y.d.t.", DAYZONE, 9 HRS},
- {"hst", ZONE, 10 HRS}, /* Hawaii */
- {"h.s.t.", ZONE, 10 HRS},
- {"hdt", DAYZONE, 10 HRS},
- {"h.d.t.", DAYZONE, 10 HRS},
- {"bst", ZONE, 11 HRS}, /* Bering */
- {"b.s.t.", ZONE, 11 HRS},
- {"bdt", DAYZONE, 11 HRS},
- {"b.d.t.", DAYZONE, 11 HRS},
-
- {"gmt", ZONE, 0 HRS},
- {"g.m.t.", ZONE, 0 HRS},
-
- {"aest", ZONE, -10 HRS}, /* Australian Eastern Time */
- {"a.e.s.t.", ZONE, -10 HRS},
- {"aesst", DAYZONE, -10 HRS}, /* Australian Eastern Summer Time */
- {"a.e.s.s.t.", DAYZONE, -10 HRS},
- {"acst", ZONE, -(9 HRS + HALFHR)}, /* Australian Central Time */
- {"a.c.s.t.", ZONE, -(9 HRS + HALFHR)},
- {"acsst", DAYZONE, -(9 HRS + HALFHR)}, /* Australian Central Summer */
- {"a.c.s.s.t.", DAYZONE, -(9 HRS + HALFHR)},
- {"awst", ZONE, -8 HRS}, /* Australian Western Time */
- {"a.w.s.t.", ZONE, -8 HRS}, /* (no daylight time there, I'm told */
- {0, 0, 0}};
-
- struct table unittb[] = {
- {"year", MUNIT, 12},
- {"month", MUNIT, 1},
- {"fortnight", UNIT, 14*24*60},
- {"week", UNIT, 7*24*60},
- {"day", UNIT, 1*24*60},
- {"hour", UNIT, 60},
- {"minute", UNIT, 1},
- {"min", UNIT, 1},
- {"second", SUNIT, 1},
- {"sec", SUNIT, 1},
- {0, 0, 0}};
-
- struct table othertb[] = {
- {"tomorrow", UNIT, 1*24*60},
- {"yesterday", UNIT, -1*24*60},
- {"today", UNIT, 0},
- {"now", UNIT, 0},
- {"last", NUMBER, -1},
- {"this", UNIT, 0},
- {"next", NUMBER, 2},
- {"first", NUMBER, 1},
- /* {"second", NUMBER, 2}, */
- {"third", NUMBER, 3},
- {"fourth", NUMBER, 4},
- {"fifth", NUMBER, 5},
- {"sixth", NUMBER, 6},
- {"seventh", NUMBER, 7},
- {"eigth", NUMBER, 8},
- {"ninth", NUMBER, 9},
- {"tenth", NUMBER, 10},
- {"eleventh", NUMBER, 11},
- {"twelfth", NUMBER, 12},
- {"ago", AGO, 1},
- {0, 0, 0}};
-
- struct table milzone[] = {
- {"a", ZONE, 1 HRS},
- {"b", ZONE, 2 HRS},
- {"c", ZONE, 3 HRS},
- {"d", ZONE, 4 HRS},
- {"e", ZONE, 5 HRS},
- {"f", ZONE, 6 HRS},
- {"g", ZONE, 7 HRS},
- {"h", ZONE, 8 HRS},
- {"i", ZONE, 9 HRS},
- {"k", ZONE, 10 HRS},
- {"l", ZONE, 11 HRS},
- {"m", ZONE, 12 HRS},
- {"n", ZONE, -1 HRS},
- {"o", ZONE, -2 HRS},
- {"p", ZONE, -3 HRS},
- {"q", ZONE, -4 HRS},
- {"r", ZONE, -5 HRS},
- {"s", ZONE, -6 HRS},
- {"t", ZONE, -7 HRS},
- {"u", ZONE, -8 HRS},
- {"v", ZONE, -9 HRS},
- {"w", ZONE, -10 HRS},
- {"x", ZONE, -11 HRS},
- {"y", ZONE, -12 HRS},
- {"z", ZONE, 0 HRS},
- {0, 0, 0}};
-
- lookup(id) char *id;
- {
- #define gotit (yylval=i->value, i->type)
- #define getid for(j=idvar, k=id; *j++ = *k++; )
-
- char idvar[20];
- register char *j, *k;
- register struct table *i;
- int abbrev;
-
- getid;
- if (strlen(idvar) == 3) abbrev = 1;
- else if (strlen(idvar) == 4 && idvar[3] == '.') {
- abbrev = 1;
- idvar[3] = '\0';
- }
- else abbrev = 0;
-
- if (islower(*idvar)) *idvar = toupper(*idvar);
-
- for (i = mdtab; i->name; i++) {
- k = idvar;
- for (j = i->name; *j++ == *k++;) {
- if (abbrev && j==i->name+3) return gotit;
- if (j[-1] == 0) return gotit;
- }
- }
-
- getid;
- for (i = mztab; i->name; i++)
- if (strcmp(i->name, idvar) == 0) return gotit;
-
- for (j = idvar; *j; j++) if (isupper(*j)) *j = tolower(*j);
- for (i=mztab; i->name; i++)
- if (strcmp(i->name, idvar) == 0) return gotit;
-
- getid;
- for (i=unittb; i->name; i++)
- if (strcmp(i->name, idvar) == 0) return gotit;
-
- if (idvar[strlen(idvar)-1] == 's') idvar[strlen(idvar)-1] = '\0';
- for (i=unittb; i->name; i++)
- if (strcmp(i->name, idvar) == 0) return gotit;
-
- getid;
- for (i = othertb; i->name; i++)
- if (strcmp(i->name, idvar) == 0) return gotit;
-
- getid;
- if (strlen(idvar) == 1 && isalpha(*idvar)) {
- if (isupper(*idvar)) *idvar = tolower(*idvar);
- for (i = milzone; i->name; i++)
- if (strcmp(i->name, idvar) == 0) return gotit;
- }
-
- return(ID);
- }
-
- time_t getdate(p, now) char *p; struct timeb *now;
- {
- #define mcheck(f) if (f>1) err++
- time_t monthadd();
- int err;
- struct tm *lt;
- struct timeb ftz;
-
- time_t sdate, tod;
-
- lptr = p;
- if (now == ((struct timeb *) NULL)) {
- now = &ftz;
- ftime(&ftz);
- }
- lt = localtime(&now->time);
- year = lt->tm_year;
- month = lt->tm_mon+1;
- day = lt->tm_mday;
- relsec = 0; relmonth = 0;
- timeflag=zoneflag=dateflag=dayflag=relflag=0;
- ourzone = now->timezone;
- daylight = MAYBE;
- hh = mm = ss = 0;
- merid = 24;
-
- if (err = yyparse()) return (-1);
-
- mcheck(timeflag);
- mcheck(zoneflag);
- mcheck(dateflag);
- mcheck(dayflag);
-
- if (err) return (-1);
-
- if (dateflag || timeflag || dayflag) {
- sdate = dateconv(month,day,year,hh,mm,ss,merid,ourzone,daylight);
- if (sdate < 0) return -1;
- }
- else {
- sdate = now->time;
- if (relflag == 0)
- sdate -= (lt->tm_sec + lt->tm_min*60 +
- lt->tm_hour*(60L*60L));
- }
-
- sdate += relsec;
- sdate += monthadd(sdate, relmonth);
-
- if (dayflag && !dateflag) {
- tod = dayconv(dayord, dayreq, sdate);
- sdate += tod;
- }
-
- return sdate;
- }
-
- yyerror(s) char *s;
- {}
- !E!O!F!
-
- echo Part 2 of 7 extracted.
-
-
-